var agenda = new liwe.module ( "agenda" );

agenda._cache = {};

agenda._users = {};
agenda._groups = {};
agenda._calendars = {};

function Agenda ( id_cal, attrs ) // cal_name
{
	if ( ! id_cal ) return;

	var self = this;
	this._name = id_cal;//cal_name;
	if ( ! attrs ) attrs = {};
	//Default value for 'show' param is true, pass it as false if you want to init the calendar without showing it
	this._show_on_init = attrs.get ( 'show', true );
	this._dest_div = attrs.get ( 'dest_div', 'AG-calendar' );
	this._cal_data = {}; 
	this._evts_cache = {};
	this._events_list = {};
	this._month_cached = [];
	this._curr_date = new Date ();
	this._pops = {};
	this._pop_height = 'auto';
	this._pop_width = 200;
	this._loading_list = false;
	this._cell_content_cback = ( attrs.get ( 'cell_content' ) ) ? attrs.cell_content : agenda._cal_cell_content;	
	//define popbox cbacks
	this._pops_cbacks = {
				'pre-show' : null,
				'post-show': null,
				'hide'     : null		
				};

	this.cal = new WWL.calendar ( this._name, attrs );
	this.cal._calendar.is_popup = false;
	this.cal.set_attr ( 'agenda_name', this._name );
	//option not present in WWL
	this.cal._calendar.show_days_labels = attrs.get ( 'days_labels' , 'T' );
	// define calendar cbacks
	this.cal.set_event ( 'date_shown', agenda._date_shown );
	this.cal.set_event ( 'date_changed',agenda.add_event );
	this.cal.set_event ( 'onclick', agenda.add_event );

	this.cal.set_event ( 'day_content', this._cell_content_cback ); 
	// redefine to change event click handler
	//this.event_cback = null;
	this.cbacks = {
			'post-init' : attrs.get ( 'post-init', null ),
			'post-show' : attrs.get ( 'post-show', null ),
			'event-cback' : null //must be passed as a string
			};

	this._cal_properties ( id_cal, function ()
		{
			agenda._instances [ self._name ] = self;
			//console.debug ( "\n\n_cal_properties: %s, _cache = %o\n" , id_cal, agenda._cache );
			if ( ! self._show_on_init ) 
			{
				console.warn ( "\n_show_on_init set to false ( id_cal = %s )\n" % self._name );
				self.get_events_list ( id_cal, null, null, null, self.cbacks [ 'post-init' ], true );
				return;
			}
			self.show ( self._this_div );
		} );
}

Agenda.prototype._month_range = function ( month, year )
{
	var cal_obj = this.cal._calendar;
	month = ( ! month ) ? cal_obj.cur_month : month -1;
	if ( ! year ) year = cal_obj.cur_year;
	var res = {};
	res.last = cal_obj.days_in_month.get ( month );
	res.date_start = String.format ( "%s-%s-%s" , year, month + 1, '1' );
	res.date_end = String.format ( "%s-%s-%s" , year, month + 1, res.last );
	return res;
};

Agenda.prototype.set_popup = function ( bool )
{
	this.cal._calendar.is_popup = bool;
};

Agenda.prototype._cal_properties = function ( cal_name, cback )
{
	var self = this;

	function _action ( data )
	{
		self._cal_data = data;
		if ( cback ) cback ();
	};

	var cache_data, id = agenda._is_id ( cal_name );
	if ( id && agenda._cache.get ( 'calendars' ) )
	{
		cache_data = agenda._cache.calendars.get ( id , null );
		if ( cache_data ) 
		{
			_action ( cache_data );
			return;
		}
	}

	agenda.ajax ( { 'action' : 'agenda.ajax.get_calendar', 'cal_name' : '', 'id_cal' : id }, function ( values )
				{
					if ( values.count () < 1 ) return;
					_action ( values );
					if ( ! agenda._cache.get ( 'calendars' ) ) agenda._cache [ 'calendars' ] = {};
					agenda._cache [ 'calendars' ].inherits ( values.get ( 'calendar' ) );
				} );
};

Agenda.prototype.show = function ( dest_div )
{
	if ( ! dest_div ) dest_div = this._dest_div;
	if ( $ ( dest_div ) ) $( dest_div, '' );
	var self = this;
	var res = this._month_range ();
	this.get_events_list ( this._name, '', res.date_start, res.date_end, function ()
		{ 
			if ( $( dest_div ) )
			{
				self.cal._calendar.render ( dest_div );
				self.cal._calendar.show ( dest_div );
			}
			//these divs are typically used in admin page 
			if ( $( 'AG-cal-title' ) )
				$( 'AG-cal-title', String.formatDict ( agenda.templates [ 'cal-title' ], { 'cal_name' : agenda._calendars.get ( self._name, '' ) } ) );
			if ( $( 'AG-swicth-mode' ) )
				$( 'AG-swicth-mode', String.formatDict ( agenda.templates [ 'switch-mode' ], { 'id_cal' : self._name } ) );
			if ( self.cbacks [ 'post-show' ] ) self.cbacks [ 'post-show' ] ();
		}, true );
};

Agenda.prototype.get_events_list = function ( id_cal, id_evt, date_start, date_end, cback, full_month )
{
	//FIXME: check if is better use this._name instead of  this._cal_data.id_cal
	id_cal = ( id_cal ) ? id_cal : this._cal_data.id_cal;
	if ( ! date_end )
	{
		var start = ( date_start ) ? new Date ( start ) : new Date ();
		var month_range = this._month_range ( start.getMonth () + 1,  start.getFullYear () );
		date_start = month_range.date_start;
		date_end = month_range.date_end;
	}

	var self = this;
	var cal_obj = this.cal._calendar;
	var evts, vals = {
			'action' : 'agenda.ajax.get_event',
			'id_cal' : id_cal,
			'id_evt' : id_evt,
			'date_start' : date_start,
			'date_end' : date_end
			};

	this.clear_popbox ();
	this._loading_list = true;
	// find if full month has been cached
	function _cmp_month ()
	{
		var res = false, month = Date.formatted ( "%Y-%m-%d", date_start ).substr ( 0, 7 ) ;
		self._month_cached.iterate ( function ( cmp_key )
			{
				if ( cmp_key == month ) res = true;
			} );
		return res;
	};
	
	// and check if single event has been cached
	var _cmp = _cmp_month (), month = Date.formatted ( "%Y-%m-%d", date_start ).substr ( 0, 7 ) ;
	if ( ( full_month && _cmp ) || ( id_evt && this._evts_cache.get ( id_evt ) ) )
	{
		this._loading_list = false;
		evts = this._events_list;
		if ( cback ) cback ( evts );
		return;
	};
	
	agenda.ajax ( vals, function ( data )
		{
			evts = data.get ( 'cal_event', [] );
			var tmp_key, month;
			//FIXME: need to decide if it will cache months with no events
			if ( full_month ) //&& evts.count () > 0 )
			{
				month = Date.formatted ( "%Y-%m-%d", evts [ 0 ] [ 'date_start' ] ).substr ( 0, 7 );
				self._month_cached.push ( month );
			}
			// cache results
			evts.iterate ( function ( v )
				{
					self._evts_cache [ v.id_evt ] = v;
					tmp_key = Date.formatted ( v.get ( 'date_start', '0000-00-00' ) ).substr ( 0, 10 );
					if ( ! self._events_list.get ( tmp_key ) ) self._events_list [ tmp_key ] = [];
					self._events_list [ tmp_key ].push ( v );
				} );

			self._loading_list = false;
			cal_obj.render ();

			if ( cback ) cback ( evts );
		} );
};

Agenda.prototype._purge_cache = function ()
{
	this._events_list = {};
	this._evts_cache = {};
	this._month_cached = [];
};

/*** agenda wwl popbox ***/

Agenda.prototype.popbox = function ( name, parent_div, w, h )
{
        
        if ( ! w ) w = 200;
        if ( ! h ) w = 100;
        
        if ( ! name ) name = 'pop_' + this._name;
        if ( this._pops.get ( name ) ) return;
        pop = new WWL.popbox ( name );
        pop.set_size ( w, h );
        pop.set_parent ( parent_div, 'L' );
        this._pops [ name ] = pop;
        return pop;
};
Agenda.prototype.popbox_evts_list = function ( cur_day, id_list, parent_div, cback )
{
	var ext = this._name + ':' + id_list;
	var pop_name = 'pop_' + ext
	var pop_cnt = 'popbox:' + pop_name;
	var pop = this._pops.get ( pop_name );

	if ( ! pop )
	{
		this.clear_popbox ();
		pop = this.popbox ( pop_name, $el( parent_div ), this._pop_width, this._pop_height );
		pop.set_parent ( $el ( parent_div ) );
		if ( this._pops_cbacks [ 'pre-show' ] ) this._pops_cbacks [ 'pre-show' ] ();
		pop.show ();
		var evts_list = this._events_list.get ( id_list, [] );
		$( pop_cnt, agenda._pop_evts_list ( cur_day, id_list, this._name, pop_name ) );
		if ( this._pops_cbacks [ 'post-show' ] ) this._pops_cbacks [ 'post-show' ] ();
		if ( cback ) cback ();
		return;
	};
	if ( $( pop_cnt ).style.display == 'block' )
	{
			pop.hide ();
	if ( this._pops_cbacks [ 'hide' ] ) this._pops_cbacks [ 'hide' ] ();
			return;
	}
	pop.set_parent ( parent_div );
	if ( this._pops_cbacks [ 'pre-show' ] ) this._pops_cbacks [ 'pre-show' ] ();
        pop.show ();
	if ( this._pops_cbacks [ 'post-show' ] ) this._pops_cbacks [ 'post-show' ] ();
	if ( cback ) cback ();
};

Agenda.prototype.clear_popbox = function ( name )
{
        if ( name )
        {
                this._pops [ name ].destroy ();
                delete this._pops [ name ];
                return;
        }
        var self = this;
        this._pops.iterate ( function ( v, k )
                                {
                                        self._pops [ k ].destroy ();
                                        delete self._pops [ k ];
                                } );
};

/*** os3calendar callbacks ***/

agenda._date_shown = function ( year, month, day, cal_obj )
{
	console.debug ( "-------- Agenda: year = %s, month = %s, day = %s, cal_obj = %o \n\n", year, month, day, cal_obj );
	var AG = agenda.get_instance ( cal_obj.agenda_name );
	var res = AG._month_range ();
	AG.get_events_list ( '', '', res.date_start, res.date_end, null, true );
};

agenda.add_event = function ( year, month, day, cal_obj, id_evt ) 
{
	//FIXME: in future user will be able to set events from front end
	if ( ! agenda.get ( 'admin' ) ) return;
	var sel_date = year + '-' + ( month +1 ) + '-' + day; //AG.cal._calendar.cur_date; 
	var id = 'add_evt:' + id_cal;
	var title = ( id_evt ) ? "Modifica evento" : "Nuovo evento";
	var w = 450, h = 600;
	var form = agenda._create_add_event_form ( id_evt, id_cal );
	liwe.lightbox.set_zindex ( id, 1500, true );
	liwe.lightbox.easy ( id, title, w, h );
	form.set ( id );
	form.set_value ( 'date_start', sel_date );
	form.set_value ( 'date_end', sel_date );
	if ( id_evt )
	{
		var data = AG._evts_cache.get ( id_evt );
		if ( data )
		{
			agenda._populate_form ( 'AG-addevt-form', data );
			return;
		}
		AG.get_events_list ( id_cal, id_evt, '', '', function ( evts )
			{
				data = evts [ 0 ];
				agenda._populate_form ( 'AG-addevt-form', data );
			} );
	}
	
};

/*** common functions ***/
agenda._pop_evts_list = function ( cur_day, tmp_id, id_cal, pop_name )
{
	var title = Date.formatted ( "%d/%m/%Y", tmp_id );
	var func = "agenda.pop_clear ( " + id_cal + ", '" + pop_name  + "' );";
	var head = String.formatDict ( agenda.templates [ 'mark-cell-close' ] , { 'func' : func, 'title' : title } );
	var div = new String.buffer (); 
	div.add ( head ); 
	div.add ( agenda._create_evts_list ( cur_day, tmp_id, id_cal ) );
	div.add ( agenda.templates [ 'mark-cell-footer' ] );
	return div.toString (); 
};

agenda._define_call = function ( evt, func_name )
{
	agenda [ func_name ] = function ()
	{
		agenda.dispatchEvent ( 'stats-show', null, { 'title' : evt.title, 'id_evt': evt.id_evt, 'id_cal': evt.id_cal } );
		eval ( evt.evt_cback );
	}
};

agenda._create_evts_list = function ( cur_day, tmp_id, id_cal )
{
	var AG = agenda.get_instance ( id_cal );
	var cal_obj = AG.cal._calendar;
	var evts_list = AG._events_list.get ( tmp_id );
	var func_name, d, params, div = new String.buffer ();
	
	div.add ( '<div id="' + tmp_id + '">' );
	evts_list.iterate ( function ( evt ) 
		{
			evt [ 'id_cal' ] = id_cal;
			params = String.format ( "%s, %s, %s, '', %s", cal_obj.cur_year, cal_obj.cur_month, cur_day, evt.id_evt );
			evt.func = "agenda.add_event ( " + params + " );";
			evt._time_start = Date.formatted ( "%H:%M", evt.date_start );
			evt._time_end = Date.formatted ( "%H:%M", evt.date_end );
			evt._date_start = Date.formatted ( "%d-%m-%Y", evt.date_start );
			evt._date_end = Date.formatted ( "%d-%m-%Y", evt.date_end );
			evt._day = Date.formatted ( "%Y-%m-%d", evt.date_start );
			// override per site
			evt._time_range = String.formatDict ( agenda.templates [ 'time-range' ], evt ); 
			if ( AG.cbacks [ 'event-cback' ] )
			{ 
				evt.evt_cback = String.formatDict ( AG.cbacks [ 'event-cback' ], evt );
				d = tmp_id.replace ( /-/g, '' );
				func_name = 'cell_call_' + evt.id_evt + '_' + evt.id_cal + '_' + d;
				agenda._define_call ( evt, func_name );
				evt.func = "agenda." + func_name + "()";
			}
			div.add ( String.formatDict ( agenda.templates [ 'event-row' ], evt ) );
		} );
	div.add ( '</div>' );
	return div.toString ();
};

agenda._cal_cell_content = function ( day_counter, cal_obj )
{
	var id_cal = cal_obj.get ( 'agenda_name' , 0 );
	var AG = agenda.get_instance ( id_cal );
	var tmp_key, tmp_id, tmp_date, div = '';

	tmp_date = String.format ( "%s/%s/%s", cal_obj.cur_year, ( cal_obj.cur_month + 1 ), day_counter );
	//this step is needed to format date with double digit ( datetime )
        tmp_id = Date.formatted ( "%Y-%m-%d", tmp_date );

	tmp_key = AG._events_list.get ( tmp_id );

	if ( ! tmp_key ) return div;

	div = agenda._create_evts_list ( day_counter, tmp_id, id_cal );
	return div;
}

agenda._mark_cal_cell = function ( day_counter, cal_obj )
{
	var id_cal = cal_obj.get ( 'agenda_name' , 0 );
	var AG = agenda.get_instance ( id_cal );
	var tmp_key, tmp_id, tmp_date, div = '';
	
	tmp_date = String.format ( "%s/%s/%s", cal_obj.cur_year, ( cal_obj.cur_month + 1 ), day_counter );
        tmp_id = Date.formatted ( "%Y-%m-%d", tmp_date );

	tmp_key = AG._events_list.get ( tmp_id );
	if ( ! tmp_key ) return div;

	div = String.formatDict ( agenda.templates [ 'mark-cell' ], { 'func' : "agenda.popbox_evts_list ( " + day_counter + ", '" + tmp_id + "', " + id_cal + ", event );", 'day' : day_counter } );
	return div;	
};

agenda._post_action = function ( id_cal, msg )
{
	var AG = agenda.get_instance ( id_cal );
	// clear Agenda cache
	AG._purge_cache ();
	AG.show ();
	liwe.lightbox.close ();
	system.admin.do_alert ( msg, liwe.utils.notifier.mode.NOTICE );
};

agenda._save_event = function ( form_name )
{
	if ( ! form_name ) 
	{
		var form_name = liwe.form.get ( 'AG-addevt-form' );
	}
	if ( ! form_name.check () ) return;
	var vals = form_name.get_values ();
	vals [ 'action' ] = "agenda.admin.add_event";
	agenda.ajax ( vals , function ( data )
		{
			agenda._post_action ( vals.id_cals, 'Evento salvato' );
		} );
};

agenda._del_event = function ( form_name )
{
	if ( ! form_name ) 
	{
		var form_name = liwe.form.get ( 'AG-addevt-form' );
	}
	var conf, vals = form_name.get_values ();
	vals [ 'action' ] = "agenda.admin.del_event";

	conf = confirm ( "Voui eliminare l'evento " + vals.get ( 'title', vals.get ( 'id_evt' ) ) );
	if ( ! conf ) return;

	agenda.ajax ( vals , function ( data )
		{
			agenda._post_action ( vals.id_cals, 'Evento eliminato' );
		} );
};

agenda.popbox_evts_list = function ( cur_day, id_list, id_cal, e, cback )
{
	if ( ! e ) e = window.event;
	var target = e.target ? e.target : e.srcElement;
	AG = agenda.get_instance ( id_cal );
	AG.popbox_evts_list ( cur_day, id_list, target, cback );
};

/*** internal ***/

agenda._clear_all_popbox = function ()
{
	agenda._instances.iterate ( function ( AG )
		{
			AG.clear_popbox ();	
		} );
};

agenda._24h = function ()
{
	var tmp, part, lbl, c = 0, l = 24, opts = [];
	for ( c = 0; c < l; c++ )
	{
		tmp = '';
		part = ':00';
		if ( c < 10 )
			tmp = '0'	
		tmp += c;
		lbl = tmp + part;
		opts.push ( { label : lbl, value : lbl + ':00' } );
		part = ':30';
		lbl = tmp + part;
		opts.push ( { label : lbl, value : lbl + ':00' } );
	}
	agenda._24h_opts = opts;
};

agenda._is_id = function ( value, update )
{
	function _search_id ()
	{
		// iterate on cache and look for cal_name
		var sid = false;
		cals.iterate ( function ( v, k )
			{
				if ( v.cal_name == value ) sid = v.id_cal;
			} );	
		return sid;
	}

	var cals = ( agenda._cache.get ( 'calendars' ) ) ? agenda._cache.calendars : {};
	//if _cache is empty and update is not set to true, return false
	if ( cals.count () < 1 && ! update ) return false;
	//if value is a number and it is in _cache than return value as true id
	var round = Math.round ( value );
	if ( round && cals.get ( value ) ) return value;
	//if id_cal is found return it
	var id = _search_id ();
	if ( id ) return id;
	// update cache  
	if ( update )
		agenda._update_cals_cache ( function ( value ) { agenda._is_id ( value ); } );
};

agenda._create_options = function ( key )
{
	var v, k, fields = agenda.admin._fields, data = agenda._cache [ key ];
	data.iterate ( function ( value ) {
			v = value.get ( fields [ key ][ 0 ], '' );
			k = value.get ( fields [ key ][ 1 ], '' );
			agenda.admin [ '_' + key + '_opts' ].push ( { 'label' : k, 'value' : v } );
			if ( v != '' && k != '' ) 
				agenda [ '_' + key ][ v ] = k;
		} );
};

agenda._update_cals_cache = function ( cback )
{
	agenda.ajax ( { action: 'agenda.ajax.get_calendar' }, function ( data )
		{
			agenda._cache [ 'calendars' ] = data.get ( 'calendar' );
			agenda._calendars = {};
			if ( agenda.get ( 'admin' ) ) agenda._create_options ( 'calendars' );
			if ( cback ) cback ();
		} );	
};

agenda._create_add_event_form = function ( id_evt, ids )
{
	var f = new liwe.form.instance ( 'AG-addevt-form' );
	f.hidden ( 'id_evt', id_evt );
	f.hidden ( 'id_cals', ids );
	f.label ( { value: 'Titolo evento' } );
	f.text ( { name: 'title', maxchar: '128', mandatory: true } );
	f.label ( { value: 'Descrizione evento' } );
	f.jconed ( { name: 'descr', width: 400, height: 200, value : '' } );
	f.label ( { value: 'Data inizio' } );
	f.calendar ( { name: 'date_start', time : true } );
	f.label ( { value: 'Data fine' } );
	f.calendar ( { name: 'date_end', time : true } );
	f.label ( { value: 'Permalink' } );
	f.text ( { name: 'permalink', maxchar: '40' } );
	f.label ( { value: 'Etichette' } );
	f.tags ( { name: 'tags' } );
	f.label ( { value: 'Visibile' } );
	f.checkbox ( { name: 'visible' } );
	f.button ( { name: 'salva', value: 'Salva evento', 'class': 'green', onclick: agenda._save_event, nonl : true } );
	if ( id_evt )
		f.button ( { name: 'elimina', value: 'Elimina evento', 'class': 'red', onclick: agenda._del_event } );
	return f;
};

agenda._populate_form = function ( form_name, data )
{
	var val, f = liwe.form.get ( form_name );
	f._fields.iterate ( function ( field )
		{
			val = data.get ( field );
			if ( ! val ) return;
			f.set_value ( field, val );
		} );
};

agenda._cur_cal_shown = function ()
{
	var cal_lst = [];
	agenda._instances.iterate ( function ( AG, id_cal )
		{
			if ( AG.cal._calendar.currently_shown )
				cal_lst.push ( id_cal );
		} );
	return cal_lst;
};

agenda._exit = function ()
{
	liwe.lightbox.close ();
	agenda._instances.iterate ( function ( AG, k )
		{
			AG.clear_popbox ();	
			AG._purge_cache ();	
			delete agenda._instances [ k ];		
		} ); 
};

agenda._init_cal = function ( cal_name )
{
		
};

/*** Methods ***/

agenda.get_instance = function ( cal_name )
{
	var id_cal = agenda._is_id ( cal_name );
	return agenda._instances.get ( id_cal, false );
};

agenda.set_display_cback = function ( cal_name, cback, show )
{
	var AG = agenda.get_instance ( cal_name );
	if ( ! AG ) return false;
	AG._cell_content_cback = cback;
	AG.cal.set_event ( 'day_content', AG._cell_content_cback );	
	if ( show ) AG.show ();
	return AG;
};

agenda.set_event_cback = function ( cal_name, cback )
{
	var AG = agenda.get_instance ( cal_name );
	if ( ! AG ) return false;
	AG.cbacks [ 'event-cback' ] = cback;
	return AG;
};

//FIXME: this methods works only with defalut cbacks
agenda.switch_view = function ( cal_name, show )
{
	var AG = agenda.get_instance ( cal_name );
	if ( ! AG ) return false;
	var cbacks = [ agenda._cal_cell_content, agenda._mark_cal_cell ];
	var cb = ( AG._cell_content_cback == cbacks [ 0 ] ) ? cbacks [ 1 ] : cbacks [ 0 ];
	agenda.set_display_cback ( cal_name, cb, show );
};

agenda.set_popup = function ( cal_name, bool )
{
	var AG = agenda.get_instance ( cal_name );
	if ( ! AG ) return false;
	AG.set_popup ( bool );
	return AG;
};

agenda.get_events_list = function ( cal_name, id_cal, id_evt, date_start, date_end, cback, full_month )
{
	if ( ! id_cal && cal_name ) id_cal = agenda._is_id ( cal_name );
	var AG = agenda.get_instance ( id_cal );
	if ( ! AG ) return;
	AG.get_events_list ( id_cal, id_evt, date_start, date_end, cback, full_month );
	return AG;
};

agenda.get_event = function ( cal_name, id_evt, cback )
{
	var AG = agenda.get_instance ( cal_name );
	if ( ! AG ) return false;
	AG.get_events_list ( '', id_evt, '', '', cback );
	return AG;
};
//init a calendar without showing it
agenda.init_calendar = function ( cal_name, attrs )
{
	id_cal = agenda._is_id ( cal_name );
	if ( ! id_cal ) return false;

	var inst = agenda.get_instance ( id_cal );
	if ( inst ) return inst;

	if ( ! attrs ) attrs = {};
	if ( ! attrs.get ( 'cell_content' ) ) attrs [ 'cell_content' ] = agenda._mark_cal_cell; 
	attrs [ 'show' ] = false;
	AG = new Agenda ( id_cal, attrs );
	return AG;
};

agenda.show_calendar = function ( cal_name, dest_div, attrs )
{
	id_cal = agenda._is_id ( cal_name, true );
	if ( ! id_cal ) return;
	var AG = agenda.get_instance ( id_cal );
	agenda._clear_all_popbox ();
	if ( ! AG )
	{
		if ( ! attrs ) attrs = {};
		if ( dest_div ) attrs [ 'dest_div' ] = dest_div;
		if ( ! attrs.get ( 'cell_content' ) ) attrs [ 'cell_content' ] = agenda._mark_cal_cell; 
		AG = new Agenda ( id_cal, attrs );
		return AG;
	}
	AG.show ( dest_div );
	return AG;
};

agenda.set_pop_cbacks = function ( cal_name, name , cback )
{
	id_cal = agenda._is_id ( cal_name );
	var AG = agenda.get_instance ( id_cal );
	if ( ! AG ) return false;
	if ( AG._pops_cbacks.get ( name ) )
		AG._pops_cbacks [ name ] = cback; 
	return AG;
};

agenda.pop_clear = function ( name, popbox )
{
	var AG = agenda.get_instance ( name );
	if ( ! AG ) return false;
	var pop = AG._pops.get ( popbox );
	pop.hide ();
	AG.clear_popbox ( popbox );     
};

agenda.init = function ()
{
    agenda.valid_events ( [ 'stats-show' ] );
    agenda.addEventListener ( 'stats-show', function ( e )
    {
        if ( agenda.admin ) return;
		e.params._uid = ( user && user._uid ) ? user._uid : -1;
		var tmpl = "%(title)s - %(id_evt)s / id_cal: %(id_cal)s / uid: %(_uid)s";
		liwe.ga.event ( 'Agenda', 'Show', String.formatDict ( tmpl, e.params ) );
    } );

	agenda._instances = {};
	//agenda._24h ();
	agenda.load_templates ();
	agenda._update_cals_cache ();
	console.debug ( "Agenda init" );
};
